import socket,threading

class TalkServer:
    def __init__(self):
        self.chanel_name = []


    def accept_client(self):
        # 服务器接收消息
        # 1. 绑定一个确定的端口地址
        # 2. 启动监听端口的进程
        # 3. 准备接收消息
        # 4. 当有信息时，接受它
        server = socket.socket()
        server.bind(('192.168.0.117',1111))
        server.listen()
        print("服务器启动成功！")


        while True:        # 外死循环，用于等待建立与客户端的通道，表示可以接收无数个
            # 等待新的连接连接通道的建立，如无——>阻塞
            chanel, address = server.accept()

            print("成功连接"+str(address))    # 服务器端显示已成功连接上某IP
            chanel.send(("欢迎来自"+str(address)+"的朋友，请输入你的昵称：").encode())   # 客户端收到反馈，已连接成功，并且输入第一条消息更改昵称

            username = chanel.recv(1024).decode()   # 将客户端的第一条消息更改为昵称
            list1 = [chanel, username]
            self.chanel_name.append(list1)  # 将[通道,用户名]放入二维列表

            print('来自['+username+'->'+ str(address) + ']的朋友加入群聊')     # 服务器端显示客户端的新昵称

            for mychanel in self.chanel_name:
                mychanel[0].send(("欢迎["+username+"]加入群聊").encode())  # 客户端收到通知：已成功命名为第一条消息的内容

            threading.Thread(target=self.send_receive,args=(username,chanel,address)).start()    # 启动线程用于收发该客户端的消息



    def send_receive(self,username,chanel,address):
        # 内死循环，用于接收来自于同一个连接通道的消息，但是，如果内循环没有结束，则无法建立第二个通道——> 多线程
        while True:
            from_msg = chanel.recv(1024).decode()     # 接收客户端消息
            print('来自['+username+'->'+ str(address) + ']的消息：' + from_msg)

            if str(from_msg).startswith('@'):
                private_list = str(from_msg).split(" ")
                private_name = private_list[0][1:]
                private_msg = private_list[1]
                if self.find_chanel(private_name) != None:
                    private_chanel = self.find_chanel(private_name)
                    private_chanel.send((username + '->单独对你说：' + private_msg).encode())
                else:
                   print("你私聊的用户不存在")
            else:
                to_msg = username +"说："+ from_msg
                # chanel.send(to_msg.encode())       # 发送消息给单个客户端
                for mychanel in self.chanel_name:        #发消息给所有客户端
                    mychanel[0].send(to_msg.encode())

    def find_chanel(self,name):
        for client in self.chanel_name:
            if name == client[1]:
                return client[0]
        else:
            return None


if __name__ == '__main__':
    ts = TalkServer()
    try:
        ts.accept_client()           # 只要receive方法中有异常发生，均会进入except分支运行其代码
    except Exception as e:
        print("出现异常，服务器自行停止。")
        print(e)